package org.micro_gzm.v5.core;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import org.micro_gzm.v5.math.Matrix3D;

import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.os.SystemClock;
import android.util.Log;

public class GZMRenderer implements Renderer {
	
	private AssetManager assets;
	
	private int program;
	private int width;
	private int height;
	private long lastTime = 0;

    // attribute locations
    private int positionLoc;

    // uniform locations (Model View Perspective)
    private int MVPLoc;

    // MVP matrix
    private Matrix3D MVPMatrix = new Matrix3D();

    // rotation angle
    private float angle;
	
	private GZM3DModel model = new GZM3DModel();
	
	public GZMRenderer(Context contextIn) {
		
		assets = contextIn.getAssets();
	}
	
	
	private void init() {

		//vertex shader - this could be from an external glsl file
		String vertexShaderData = 	"uniform mat4 u_mvpMatrix;                   \n" +
									"attribute vec4 a_position;                  \n" +
									"void main(){	 							 \n" +
									"   gl_Position = u_mvpMatrix * a_position;  \n" +
									"}                                           \n";
		
		//fragment shader - this could be from an external glsl file
		String fragmentShaderData = "precision mediump float;                            \n" +
									"void main() {                                       \n" +
									"  gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );        \n" +
									"}                                                   \n";                                          	
		
		// set and load shader program
		program = GZMShader.loadProgram(vertexShaderData, fragmentShaderData);
		
		//get position location attribute
		positionLoc = GLES20.glGetAttribLocation(program, "a_position");
		
		//get uniform locations
		MVPLoc = GLES20.glGetUniformLocation(program, "u_mvpMatrix");
		
		//init the model
		model.loadFBXFile("models/microGZM_logo.fbx", assets);
//		model.setCube(1.0f);
		
		//starting rotation angle
		angle = 45.0f;
	}
	
	private void update() {
		
		if (lastTime == 0) lastTime = SystemClock.uptimeMillis();
	    long curTime = SystemClock.uptimeMillis();
	    long elapsedTime = curTime - lastTime;
	    float deltaTime = elapsedTime / 1000.0f;
	    lastTime = curTime;
	
	    Matrix3D perspective = new Matrix3D();
	    Matrix3D modelview = new Matrix3D();
	    float aspect;
	
	    // Compute a rotation angle based on time to rotate the cube
	    angle += (deltaTime * 40.0f);
	    if (angle >= 360.0f)
	        angle -= 360.0f;
	
	    // Compute the window aspect ratio
	    aspect = (float) width / (float) height;
	
	    // Generate a perspective matrix with a 60 degree FOV
	    perspective.matrixLoadIdentity();
	    perspective.perspective(60.0f, aspect, 1.0f, 20.0f);
	
	    // Generate a model view matrix to rotate/translate the cube
	    modelview.matrixLoadIdentity();
	
	    // Translate away from the viewer
	    modelview.translate(0.0f, 0.0f, -5.0f);
	
	    // Rotate the cube
	    modelview.rotate(angle, 1.0f, 0.0f, 1.0f);
	
	    // Compute the final MVP by multiplying the
	    // modevleiw and perspective matrices together
	    MVPMatrix.matrixMultiply(modelview.get(), perspective.get());
	}
	
	public void addModel(GZM3DModel modelIn) {
		
		model = modelIn;
	}

	@Override
	public void onSurfaceCreated(GL10 unused, EGLConfig config) {
		
		init();
	}

	@Override
	public void onDrawFrame(GL10 unused) {
		
		update();

        // Set the viewport
        GLES20.glViewport(0, 0, width, height);

        // Clear the color buffer
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        // Use the program object
        GLES20.glUseProgram(program);

        // Load the vertex data
        GLES20.glVertexAttribPointer(positionLoc, 3, GLES20.GL_FLOAT, false, 0, model.getVertices());
        GLES20.glEnableVertexAttribArray(positionLoc);

        // Load the MVP matrix
        GLES20.glUniformMatrix4fv(MVPLoc, 1, false, MVPMatrix.getAsFloatBuffer());

        // Draw the cube
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, model.getNumIndices(), GLES20.GL_UNSIGNED_SHORT, model.getIndices());
	}

	@Override
	public void onSurfaceChanged(GL10 unused, int widthIn, int heightIn) {
		
		//set width and height properties (viewport)
		width = widthIn;
		height = heightIn;
	}
}
